﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Lm.InferenceEngine.Test
{
    public enum FarmerPostion
    {
        Left, Right
    }

    /// <summary>
    /// 为推理引擎提供农夫带东西过桥的故事场景
    /// </summary>
    class ThroughBridge : Lm.InferenceEngine.InferenceObject
    {
        /// <summary>
        /// 农夫在左侧还是在右侧
        /// </summary>
        public FarmerPostion Farmer { get; set; }

        /// <summary>
        /// 狼是否在左侧
        /// </summary>
        public bool Left1 { get; set; }
        /// <summary>
        /// 羊是否在左侧
        /// </summary>
        public bool Left2 { get; set; }
        /// <summary>
        /// 白菜是否在左侧
        /// </summary>
        public bool Left3 { get; set; }

        /// <summary>
        /// 狼是否在右侧
        /// </summary>
        public bool Right1 { get; set; }
        /// <summary>
        /// 羊是否在右侧
        /// </summary>
        public bool Right2 { get; set; }
        /// <summary>
        /// 白菜是否在右侧
        /// </summary>
        public bool Right3 { get; set; }

        /// <summary>
        /// 见基类说明
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        override public bool SameWith(InferenceObject obj)
        {
            var target = (ThroughBridge)obj;
            return (this.Left1 == target.Left1)
                && (this.Left2 == target.Left2)
                && (this.Left3 == target.Left3)
                && (this.Right1 == target.Right1)
                && (this.Right2 == target.Right2)
                && (this.Right3 == target.Right3)
                && (this.Farmer == target.Farmer);
        }

        /// <summary>
        /// 见基类说明
        /// 根据当前状态，推导下一级可能性
        /// </summary>
        /// <returns></returns>
        override public List<InferenceObject> GenerateChildrens()
        {
            var childrens = new List<InferenceObject>();
            //产生所有的可能性
            for (int x = 0; x < 2; x++)
            {
                var left1 = x == 0;
                var right1 = !left1;
                for (int y = 0; y < 2; y++)
                {
                    var left2 = y == 0;
                    var right2 = !left2;
                    for (int z = 0; z < 2; z++)
                    {
                        var left3 = z == 0;
                        var right3 = !left3;
                        childrens.Add(new ThroughBridge() { Farmer = FarmerPostion.Left, Left1 = left1, Left2 = left2, Left3 = left3, Right1 = right1, Right2 = right2, Right3 = right3, });
                        childrens.Add(new ThroughBridge() { Farmer = FarmerPostion.Right, Left1 = left1, Left2 = left2, Left3 = left3, Right1 = right1, Right2 = right2, Right3 = right3, });
                    }
                }
            }

            var toRemovedList = new List<InferenceObject>();
            foreach (ThroughBridge child in childrens)
            {
                //排除狼吃羊和羊吃白菜的可能性
                if (child.Left2 == true
                    && (child.Left1 || child.Left3) && child.Farmer == FarmerPostion.Right
                    )
                {
                    toRemovedList.Add(child);
                }
                else if
                (child.Right2 == true
                    && (child.Right1 || child.Right3) && child.Farmer == FarmerPostion.Left
                    )
                {
                    toRemovedList.Add(child);
                }
                else
                {
                    //一次只能带一个东西
                    var i = 0;
                    if (this.Left1 != child.Left1)
                    { i++; }
                    if (this.Left2 != child.Left2)
                    { i++; }
                    if (this.Left3 != child.Left3)
                    { i++; }
                    if (i >= 2)
                    {
                        toRemovedList.Add(child);
                    }
                }
            }
            foreach (var r in toRemovedList)
            {
                childrens.Remove(r);
            }
            //农夫位置必须发生变化
            var result = childrens.Where(t => ((ThroughBridge)t).Farmer != this.Farmer).ToList();
            return result;
        }

        /// <summary>
        /// 见基类说明,全部到右侧，才能达到目标
        /// </summary>
        /// <returns></returns>
        override public bool IsSuccess()
        {
            return this.Left1 == false
                && this.Left2 == false
                && this.Left3 == false
                && this.Right1 == true
                && this.Right2 == true
                && this.Right3 == true
                && this.Farmer == FarmerPostion.Right;
        }

        public override string ToString()
        {
            return
             "左侧：" + (this.Farmer == FarmerPostion.Left ? "农夫" : "") + "," + ((this.Left1 == true) ? "狼" : "") + "," + (this.Left2 == true ? "羊" : "") + "," + (this.Left3 == true ? "白菜" : "") + "\r\n"
             + "右侧：" + (this.Farmer == FarmerPostion.Right ? "农夫" : "") + "," + ((this.Right1 == true) ? "狼" : "") + "," + (this.Right2 == true ? "羊" : "") + "," + (this.Right3 == true ? "白菜" : "");
        }
    }
}
